package com.amado.course35Concurrent;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;

public class OrderCheckerUtil {

    // 私有构造函数，防止实例化工具类
    private OrderCheckerUtil() {}

    // 检查订单的方法，返回CompletableFuture<Void>
    public static CompletableFuture<Void> checkOrder(int orderId) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟业务逻辑
            if (orderId % 2 == 0) {
                throw new IllegalArgumentException("Business check failed for order ID: " + orderId);
            }
            return null; // 如果检查通过，返回null
        }).thenAccept(result -> {
            System.out.println("Order " + orderId + " passed business check.");
        }).exceptionally(ex -> {
            System.err.println("Exception during business check for order ID: " + orderId + ", " + ex.getMessage());
            // 这里不需要重新抛出异常，而是应该处理它（例如，记录日志）
            // 然后可以返回一个completedExceptionally的CompletableFuture，但在这个工具类中，
            // 我们将简化处理，并在调用者中同步等待结果。
            return null; // 返回null或任何表示失败的值，但在这个例子中我们不需要它
        });
    }

    // 执行多个订单检查，并等待所有任务完成，然后处理任何异常
    public static void checkOrdersAndWait(List<Integer> orderIds) throws InterruptedException, ExecutionException {
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        for (int orderId : orderIds) {
            futures.add(checkOrder(orderId));
        }

        // 使用CompletableFuture.allOf来等待所有任务完成
        CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));

        // 阻塞等待所有任务完成或发生异常
        try {
            allOfFuture.get(); // 这将阻塞直到所有Future完成
        } catch (Exception e) {
            // 如果任何一个Future以异常结束，get()将抛出ExecutionException
            // 我们可以从这个异常中获取原始的异常信息
            Throwable cause = e.getCause();
            if (cause instanceof IllegalArgumentException) {
                // 这里我们实际上不需要检查是否是CompletionException，因为allOf不会直接抛出它，
                // 但如果checkOrder中的exceptionally返回了一个completedExceptionally的Future，
                // 并且我们在调用者中单独等待了那个Future，那么我们就需要检查它。
                // 在这个例子中，我们简化处理，直接获取最原始的异常。
                cause = cause.getCause();
                cause.printStackTrace();
            }
            // 处理异常，例如打印堆栈跟踪或重新抛出
            cause.printStackTrace();
            throw new RuntimeException("One or more order checks failed.", cause);
        }

        // 如果没有异常发生，打印成功消息
        System.out.println("All order checks completed successfully.");
    }

    // 示例主方法（通常不应该在工具类中包含主方法，这里只是为了演示）
    public static void main(String[] args) {
        List<Integer> orderIds = Arrays.asList(1, 2, 3, 4, 5);
        try {
            checkOrdersAndWait(orderIds);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}